import React, {useCallback, useEffect, useMemo, useState} from 'react';
import {
  Button,
  Card,
  Divider,
  Drawer,
  Empty,
  List,
  message, Popconfirm, Space,
  Typography,
} from 'antd';
import style from './Spiders.module.scss';
import {
  getSpiders,
  postCancelSpider, postSearchKey,
} from '../../network/requests';
import {
  MinusCircleOutlined,
  EyeOutlined,
  ReloadOutlined,
  SearchOutlined, PlusOutlined, DoubleRightOutlined,
} from '@ant-design/icons';
import {AutoSizer} from 'react-virtualized';
import {Link} from 'react-router-dom';
import {getSteps, OutputDisplay} from './widgets';
import {processSpider, statusIcon} from '../../utils/convert';
import {SpiderInfo} from '../../components/SpiderInfo';
import {CreateSpider} from '../../components/CreateSpider';
import {SpiderHeader} from '../../components/SpiderHeader';
import {BookDetail} from '../../components/BookDetail';

const {Text} = Typography;


function Spiders() {
  const [total, setTotal] = useState(0);
  const [loading, setLoading] = useState(true);
  const [spiders, setSpiders] = useState([]);
  const [visible, setVisible] = useState(false);
  const [pollCount, setPollCount] = useState(0);
  const [displayKey, setDisplayKey] = useState(null);
  const [currentPage, setCurrentPage] = useState(1);
  const [nowDate, setNowDate] = useState(new Date());
  const [cancelLoading, setCancelLoading] = useState({});
  const [createSpiderVisible, setCreateSpiderVisible] = useState(false);
  const [createSpiderKey, setCreateSpiderKey] = useState('');

  useEffect(() => {
    setInterval(() => {
      setNowDate(new Date());
    }, 1000);
  }, []);

  const showDrawer = (key) => {
    setVisible(true);
    setDisplayKey(key);
  };

  const cancelSpider = (key) => {
    setCancelLoading((c) => {
      return {
        ...c,
        [key]: true,
      };
    });
    postCancelSpider(key).then(() => {
      message.loading('正在取消中');
      setCancelLoading((c) => {
        return {
          ...c,
          [key]: false,
        };
      });
    }).catch((e) => {
      if (e.response.status === 400) {
        message.error('当前状态不能取消');
      } else {
        message.error(e.response.data.message);
      }
      setCancelLoading((c) => {
        return {
          ...c,
          [key]: false,
        };
      });
    });
  };

  const onClose = () => {
    setVisible(false);
  };

  useEffect(() => {
    let cancelled = false;
    getSpiders(currentPage).then((data) => {
      if (cancelled) {
        return;
      }
      setTotal(data.total);
      setSpiders(data.data);
    }).catch(() => {
      if (cancelled) {
        return;
      }
      message.error('获取爬虫信息失败');
    }).finally(() => {
      if (cancelled) {
        return;
      }
      setLoading(false);
      setTimeout(() => {
        setPollCount(pollCount + 1);
      }, 3000);
    });
    return () => {
      cancelled = true;
    };
  }, [currentPage, pollCount]);

  const searchSpiders = useCallback(() => {
    return getSpiders(currentPage).then((data) => {
      setTotal(data.total);
      setSpiders(data.data);
    }).catch(() => {
      message.error('获取爬虫信息失败');
    });
  }, [currentPage]);

  const parsedSpiders = useMemo(() => {
    return spiders.map(processSpider);
  }, [spiders]);

  const drawerItem = parsedSpiders[displayKey];

  return (
    <>
      {drawerItem &&
        <Drawer
          destroyOnClose={true}
          contentWrapperStyle={{width: '600px'}}
          title={<>
            {statusIcon[drawerItem.status]}任务 {drawerItem.id}
          </>}
          placement="right" onClose={onClose} visible={visible}
        >
          {getSteps(drawerItem)}
          <AutoSizer className={style.forceMargin} disableWidth>
            {({height}) => (
              <Card
                className={style.output}
                bodyStyle={{height: Math.max(300, height - 280)}}
                size={'small'}
                title={<Text type={'secondary'}>输出</Text>}
              >
                {
                    drawerItem.formattedOutput.length ?
                        <OutputDisplay output={drawerItem.formattedOutput}/> :
                        <Empty/>
                }
              </Card>
            )}
          </AutoSizer>
        </Drawer>
      }
      <Button type={'primary'} icon={<PlusOutlined/>} onClick={() => {
        setCreateSpiderKey('');
        setCreateSpiderVisible(true);
      }}>新建爬虫任务</Button>
      <Divider>爬虫任务</Divider>
      <List
        loading={loading}
        itemLayout="vertical"
        size="large"
        pagination={{
          onChange: (page) => {
            setLoading(true);
            setCurrentPage(page);
          },
          current: currentPage,
          pageSize: 10,
          total: total,
          position: 'bottom',
          showSizeChanger: false,
          disabled: loading,
        }}
        dataSource={parsedSpiders}
        renderItem={(item, idx) => (
          <>
            <Card
              title={<SpiderHeader spider={item}/>}
              bordered={false}
              className={style.card}
            >
              <List.Item
                style={{padding: 0}}
                key={item.id}
                actions={[
                  <Button
                    disabled={item.status !== 'queuing' && item.status !== 'running'}
                    key={1}
                    loading={cancelLoading[item.id]}
                    onClick={() => cancelSpider(item.id)}
                    className={style.action}
                    size={'small'} type={'link'}
                    icon={<MinusCircleOutlined/>}>取消</Button>,
                  <Button
                    key={2}
                    onClick={() => showDrawer(idx)}
                    className={style.action}
                    size={'small'} type={'link'}
                    icon={<EyeOutlined/>}>详情</Button>,
                  <Link
                    key={3}
                    to={(item.type === 'comment' ? '/comments?query=' : '/?query=') + encodeURIComponent(item.key)}>
                    <Button
                      className={style.action}
                      size={'small'} type={'link'}
                      icon={<SearchOutlined/>}>
                              查看结果</Button>
                  </Link>,
                          item.type === 'comment' ?
                              <Popconfirm onConfirm={() => {
                                postSearchKey({
                                  maxCount: 0,
                                  platform: ['comment'],
                                  key: item.key,
                                }).then(() => {
                                  message.success('创建成功');
                                }).catch(() => {
                                  message.error('创建失败');
                                });
                              }} title={'爬取这本书的评论？'} key={6}><Button
                                  className={style.action}
                                  size={'small'} type={'link'}
                                  icon={<ReloadOutlined/>}>重新爬取评论
                                </Button>
                              </Popconfirm> :
                              <Button
                                key={4}
                                onClick={() => {
                                  setCreateSpiderKey(item.key);
                                  setCreateSpiderVisible(true);
                                }}
                                className={style.action}
                                size={'small'} type={'link'}
                                icon={<ReloadOutlined/>}>重新索引
                              </Button>,
                ]}
              >
                <SpiderInfo
                  parsedSpider={item}
                  nowDate={nowDate}
                />
              </List.Item>
            </Card>
            {
              item.book && <Space className={style.attachment} align={'start'}>
                <DoubleRightOutlined className={style.clipIcon}/>
                <BookDetail book={item.book} small/>
              </Space>
            }
          </>
        )}
      />
      <CreateSpider
        visible={createSpiderVisible}
        initKey={createSpiderKey}
        callback={(created) => {
          setCreateSpiderVisible(false);
          if (created) {
            setLoading(true);
            setCurrentPage(1);
            searchSpiders();
          }
        }}
      />
    </>
  );
}

export default Spiders;
